import requests
import traceback
import logging
from celery import shared_task

from django.utils import timezone

from connection.services import connection_service, certificate_service
from libs.enums import PartnerType
from datacenter.services import dataware_service
from task.models import TaskLog


logger = logging.getLogger()


@shared_task
def cron_pull_connection_data(connection_id):
    start_at = timezone.now().astimezone(timezone.get_current_timezone())
    today = start_at.date()
    success, content = False, ''
    try:
        connection = connection_service.get_connection_by_id(connection_id)
        success, content = run_pull_connection_data(connection)
        if success:
            content = '成功'
            connection.latest_pull_data_at = start_at
            connection.save()
    except Exception:
        content = f'执行异常：{traceback.format_exc()}'

    end_at = timezone.now().astimezone(timezone.get_current_timezone())
    time_spent = int((end_at.timestamp() - start_at.timestamp()) * 1000)
    TaskLog.objects.create(
        connection_id=connection_id,
        date=today,
        start_at=start_at,
        end_at=end_at,
        time_spent=time_spent,
        success=success,
        content=content
    )


def run_pull_connection_data(connection):
    logger.info('互联定时任务：开始执行')
    other_side_certificate = connection_service.get_other_side_certificate(connection.id)
    if not connection or not other_side_certificate or connection.partner.type != PartnerType.ORG.value:
        content = '未与对方建立互联'
        logger.info(content)
        return False, content
    is_success, content = pull_partner_info(connection, other_side_certificate)
    if not is_success:
        return is_success, content
    is_success, content = pull_entity_data(connection, other_side_certificate)
    if not is_success:
        logger.info(content)
        return is_success, content
    logger.info('互联定时任务：执行完成')
    return True, ''


def pull_partner_info(connection, certificate):
    logger.info('定时更新互联企业的企业信息:开始执行')
    server, headers = certificate_service.get_server_and_headers(certificate.data)
    api = f'{server}/openapi/app/info'
    try:
        response = requests.get(api, headers=headers)
        if response.status_code != 200:
            content = f'pull_partner_info失败，接口调用失败，状态码：{response.status_code}，响应信息：{response.text}'
            logger.error(content)
            return False, content
        data = response.json()
        partner = connection.partner
        partner.detail = data
        partner.save()
    except Exception:
        content = f'pull_partner_info异常，{traceback.format_exc()}'
        logger.error(content)
        return False, content
    logger.info('定时更新互联企业的企业信息：执行完成')
    return True, ''


def pull_entity_data(connection, certificate):
    ''' 定时更新互联企业的授权数据
    '''
    logger.info('定时更新互联企业的授权数据:开始执行')
    server, headers = certificate_service.get_server_and_headers(certificate.data)
    api = f'{server}/openapi/data-center/data'
    try:
        entities = certificate.data.get('entities', [])
        for entity in entities:
            entity_key = entity.get('key')
            entity_primary_key = entity.get('primary_key')
            entity_last_updated_at_key = entity.get('last_updated_at_key')
            if not entity_key or not entity_primary_key:
                continue
            params = {
                'entity_key': entity_key,
                'page_size': 1000,
                'page': 1,
            }
            if entity_last_updated_at_key:
                params['last_updated_at'] = connection.latest_pull_data_at

            response = requests.get(api, params=params, headers=headers)
            if response.status_code != 200:
                content = f'pull_entity_data失败，接口访问失败，状态码：{response.status_code}，响应信息：{response.text}'
                logger.error(content)
                return False, content

            data = response.json()
            items = data.get('items')
            model = dataware_service.get_model(certificate, entity_key)
            for item in items:
                data_primary_key = item.get(entity_primary_key)
                if not data_primary_key:
                    continue
                primary_key_field = {entity_primary_key: data_primary_key}
                model.objects.update_or_create(
                    **primary_key_field,
                    defaults=item
                )
    except Exception:
        content = f'pull_entity_data异常，{traceback.format_exc()}'
        logger.error(content)
        return False, content
    logger.info('定时更新互联企业的授权数据:执行完成')
    return True, ''
